package com.margiel.rozkladowka.writer.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.margiel.rozkladowka.model.Stop;
import com.margiel.rozkladowka.model.TimeTable;
import com.margiel.rozkladowka.model.Vehicle;

public class TimeTableFile {
	public final Logger log = Logger.getLogger(this.getClass());

	private Map<String, String> codeToNos;
	private Map<String, String> codeToStops;
	private Map<String, String> codeToDirectionEnd;

	private Pattern cleanPattern;
	public TimeTableFile() {
		codeToNos = new LinkedHashMap<String, String>();
		codeToStops = new LinkedHashMap<String, String>();
		codeToDirectionEnd = new LinkedHashMap<String, String>();
		cleanPattern = Pattern.compile("\\d+");
	}
	
	public int addVehicles(List<Vehicle> vehicles){
		log.debug(" entering...");
		int i = codeToNos.size();
		for (Vehicle vehicle : vehicles) {
			if (codeToNos.containsValue(vehicle.getNo()) == false){
				log.debug("adding new No["+vehicle.getNo()+"]");
				codeToNos.put("[V"+(i++)+"]", vehicle.getNo());
			}
		}
		return codeToNos.size();
	}
	public int addStops(List<Vehicle> vehicles){
		log.debug(" entering...");
		int i = codeToNos.size();
		Set<String> stopSet = new HashSet<String>();
		for (Vehicle vehicle : vehicles) {
			for (TimeTable timeTable : vehicle.getTimeTables()) {
				for (Stop stop : timeTable.getStops()) {
//					addStop(stop);
					stopSet.add(stop.getName());
				}
			}
		}
		List<String> stops = new ArrayList<String>(stopSet);
		Collections.sort(stops);
		for (String stop : stops) {
			addStop(stop);
		}
		return codeToStops.size();
	}
	
	public int addStop(Stop stop){
		log.debug("[addStop], entering...");
		String stopName = stop.getName().intern();
		String stopNameClean = cleanPattern.matcher(stopName).replaceAll("").intern();
		String stopCode=null;
		String stopRest = stopName.replaceFirst(stopNameClean, "");
		log.debug("[addStop], stopName["+stopName+"], stopNameClean["+stopNameClean+"], stopRest["+stopRest+"]");
		if (stopName.equals(stopNameClean) == false && codeToStops.containsValue(stopNameClean) == false){
			log.debug("[addStop], creating new stopCode");
			int i = codeToStops.size();
			stopCode="[S"+(i++)+"]";
			log.debug("[addStop], stopCode["+stopCode+"]");
			codeToStops.put(stopCode, stopNameClean);
		}else if (stopName.equals(stopNameClean) == false){
			log.debug("[addStop], getting stopCode from map");
			for (Map.Entry<String, String> codeToStop : codeToStops.entrySet()) {
				if (codeToStop.getValue().equals(stopNameClean)){
					stopCode=codeToStop.getKey();
					log.debug("[addStop], stopCode found["+stopCode+"]");
					break;
				}
			}
		}
		if(stopCode == null){
			log.debug("[addStop], adding stop without SC");
			codeToStops.put("[S"+codeToStops.size()+"]", stopName);
		}else{
			log.debug("[addStop], adding stop with SC["+stopCode+stopRest+"]");
			codeToStops.put("[S"+codeToStops.size()+"]", stopCode+stopRest);
		}
		return codeToStops.size();
	}
	
	public void addStop(String stop){
		if(codeToStops.containsValue(stop) == false){
			codeToStops.put("[S"+codeToStops.size()+"]", stop);
		}
	}
	public void addDirectionEnd(String directionEnd){
		if(codeToDirectionEnd.containsValue(directionEnd) == false){
			codeToDirectionEnd.put("[D"+codeToDirectionEnd.size()+"]", directionEnd);
		}
	}

	/**
	 * Constructs a <code>String</code> with all attributes
	 * in name = value format.
	 *
	 * @return a <code>String</code> representation 
	 * of this object.
	 */
	public String toString()
	{
	    final String TAB = "    ";
	    
	    String retValue = "";
	    
	    retValue = "TimeTableFile ( "
	        + super.toString() + TAB
	        + "log = " + this.log + TAB
	        + "codeToNos = " + this.codeToNos + TAB
	        + "codeToStops = " + this.codeToStops + TAB
	        + "cleanPattern = " + this.cleanPattern + TAB
	        + " )";
	
	    return retValue;
	}

	public Map<String, String> getCodeToNos() {
		return codeToNos;
	}

	public Map<String, String> getCodeToStops() {
		return codeToStops;
	}
	
	
	public Map<String, String> getCodeToDirectionEnd() {
		return codeToDirectionEnd;
	}

	public int addDirectionEnds(List<Vehicle> vehicles){
		log.debug("[addDirectionEnds], entering...");
		int i = codeToDirectionEnd.size();
		Set<String> directionEndSet = new HashSet<String>();
		for (Vehicle vehicle : vehicles) {
			for (TimeTable timeTable : vehicle.getTimeTables()) {
				directionEndSet.add(timeTable.getSourceStop().intern());
				directionEndSet.add(timeTable.getDestinationStop().intern());
			}
		}
		List<String> directionEndList = new ArrayList<String>(directionEndSet);
		Collections.sort(directionEndList);
		for (String directionEnd : directionEndList) {
			addDirectionEnd(directionEnd);
		}
		return codeToDirectionEnd.size();
	}
	
	
}
